// Enum Test Suite - Comprehensive testing with assertions
// Tests both simple enums and Rust-style enums with data

// ============= Simple Enums (no data) =============
type Status enum {
    Pending,
    Running,
    Completed,
    Failed
}

type Color enum {
    Red,
    Green,
    Blue
}

// ============= Enums with Data (Rust-style) =============

// Result type - common pattern for error handling
type Result enum {
    Ok(int),
    Error(int)
}

// Value type - different data types
type Value enum {
    Int(int),
    Float(float64),
    Bool(bool)
}

// Point type - multi-parameter variants
type Point enum {
    Point2D(int, int),
    Point3D(int, int, int)
}

// TaskStatus - mixed variants (with and without data)
type TaskStatus enum {
    Idle,
    Processing(int),
    Done(int),
    Cancelled
}

// Message type - with String data
type Message enum {
    Text(String),
    Error(String),
    Warning(String)
}

func test_enum_suite() {
    println("=== Enum Test Suite ===\n")

    // Test 1: Basic enum values
    println("[Test 1] Basic enum values")
    assert(Status::Pending == 0, "Status::Pending should be 0")
    assert(Status::Running == 1, "Status::Running should be 1")
    assert(Status::Completed == 2, "Status::Completed should be 2")
    assert(Status::Failed == 3, "Status::Failed should be 3")

    assert(Color::Red == 0, "Color::Red should be 0")
    assert(Color::Green == 1, "Color::Green should be 1")
    assert(Color::Blue == 2, "Color::Blue should be 2")
    println("  ✓ All enum variants have correct values\n")

    // Test 2: Enum assignment
    println("[Test 2] Enum assignment")
    var status Status = Status::Pending
    assert(status == Status::Pending, "Initial assignment failed")
    assert(status == 0, "Status::Pending should equal 0")

    status = Status::Running
    assert(status == Status::Running, "Reassignment to Running failed")
    assert(status == 1, "Status::Running should equal 1")

    status = Status::Completed
    assert(status == Status::Completed, "Reassignment to Completed failed")

    status = Status::Failed
    assert(status == Status::Failed, "Reassignment to Failed failed")
    println("  ✓ Enum assignment works correctly\n")

    // Test 3: Enum comparison
    println("[Test 3] Enum comparison")
    assert(status != Status::Pending, "status should not equal Pending")
    assert(status == Status::Failed, "status should equal Failed")

    var color Color = Color::Green
    assert(color == Color::Green, "Color equality failed")
    assert(color != Color::Red, "Color inequality failed (Red)")
    assert(color != Color::Blue, "Color inequality failed (Blue)")
    println("  ✓ Enum comparison works correctly\n")

    // Test 4: Multiple enum types
    println("[Test 4] Multiple enum types")
    var s Status = Status::Completed
    var c Color = Color::Blue

    assert(s == Status::Completed, "Status assignment failed")
    assert(c == Color::Blue, "Color assignment failed")
    assert(s == 2, "Status::Completed should be 2")
    assert(c == 2, "Color::Blue should be 2")

    s = Status::Pending
    c = Color::Red
    assert(s == 0, "Both should be 0")
    assert(c == 0, "Both should be 0")
    println("  ✓ Multiple enum types work independently\n")

    // Test 5: Enum as function parameter
    println("[Test 5] Enum as function parameter")
    var code int = get_status_code(Status::Pending)
    assert(code == 100, "Pending status code should be 100")

    code = get_status_code(Status::Running)
    assert(code == 200, "Running status code should be 200")

    code = get_status_code(Status::Completed)
    assert(code == 300, "Completed status code should be 300")

    code = get_status_code(Status::Failed)
    assert(code == 400, "Failed status code should be 400")
    println("  ✓ Enum as parameter works correctly\n")

    // Test 6: Enum as return value
    println("[Test 6] Enum as return value")
    var ret_status Status = get_initial_status()
    assert(ret_status == Status::Pending, "Return value should be Pending")

    ret_status = get_running_status()
    assert(ret_status == Status::Running, "Return value should be Running")

    ret_status = get_final_status()
    assert(ret_status == Status::Completed, "Return value should be Completed")
    println("  ✓ Enum as return value works correctly\n")

    // ============= Enum with Data Tests =============

    // Test 7: Basic enum with data construction
    println("[Test 7] Enum with data - Basic construction")
    var result Result = Result::Ok(42)
    println("  Created Result::Ok(42)")

    result = Result::Error(404)
    println("  Created Result::Error(404)")

    result = Result::Ok(200)
    println("  Reassigned to Result::Ok(200)")
    println("  ✓ Basic construction works correctly\n")

    // Test 8: Different data types
    println("[Test 8] Enum with data - Different types")
    var v1 Value = Value::Int(100)
    println("  Created Value::Int(100)")

    var v2 Value = Value::Float(3.14)
    println("  Created Value::Float(3.14)")

    var v3 Value = Value::Bool(true)
    println("  Created Value::Bool(true)")

    v1 = Value::Float(2.71)
    println("  Reassigned v1 to Value::Float(2.71)")
    println("  ✓ Different types work correctly\n")

    // Test 9: Multi-parameter variants
    println("[Test 9] Enum with data - Multi-parameter")
    var p1 Point = Point::Point2D(10, 20)
    println("  Created Point::Point2D(10, 20)")

    var p2 Point = Point::Point3D(1, 2, 3)
    println("  Created Point::Point3D(1, 2, 3)")

    p1 = Point::Point2D(100, 200)
    println("  Reassigned p1 to Point::Point2D(100, 200)")
    println("  ✓ Multi-parameter variants work correctly\n")

    // Test 10: Mixed variants (with and without data)
    println("[Test 10] Enum with data - Mixed variants")
    var task TaskStatus = TaskStatus::Idle
    println("  Created TaskStatus::Idle (unit variant)")

    task = TaskStatus::Processing(50)
    println("  Created TaskStatus::Processing(50) (data variant)")

    task = TaskStatus::Done(100)
    println("  Created TaskStatus::Done(100)")

    task = TaskStatus::Cancelled
    println("  Created TaskStatus::Cancelled (unit variant)")
    println("  ✓ Mixed variants work correctly\n")

    // Test 11: Enum with data as function parameter
    println("[Test 11] Enum with data - Function parameter")
    var dummy1 int = process_result(result)
    println("  Passed Result to function")

    var dummy2 int = process_value(v1)
    println("  Passed Value to function")
    println("  ✓ Function parameter works correctly\n")

    // Test 12: Enum with data as return value
    println("[Test 12] Enum with data - Return value")
    var r1 Result = create_success()
    println("  Received Result::Ok(200)")

    var r2 Result = create_error()
    println("  Received Result::Error(404)")

    var v Result = create_result_from_value(42)
    println("  Received Result::Ok(42)")
    println("  ✓ Return value works correctly\n")

    // Test 13: Match with enum - basic
    println("[Test 13] Match expression with enum - basic")
    var match_test Result = Result::Ok(42)
    var value int = match match_test {
        Result::Ok(x) -> x,
        Result::Error(code) -> code
    }
    print("  Matched value from Ok(42): ")
    println(value)
    assert(value == 42, "Should extract 42 from Result::Ok(42)")
    println("  ✓ Basic match with enum works\n")

    // Test 14: Match with Error variant
    println("[Test 14] Match expression with Error variant")
    match_test = Result::Error(404)
    var error_code int = match match_test {
        Result::Ok(x) -> 0,
        Result::Error(code) -> code
    }
    print("  Error code: ")
    println(error_code)
    assert(error_code == 404, "Should extract 404 from Result::Error(404)")
    println("  ✓ Error variant match works\n")

    // Test 15: Match with computation
    println("[Test 15] Match with computation in arm")
    match_test = Result::Ok(10)
    var doubled int = match match_test {
        Result::Ok(x) -> x * 2,
        Result::Error(code) -> code
    }
    print("  Doubled value: ")
    println(doubled)
    assert(doubled == 20, "Should compute 10 * 2 = 20")
    println("  ✓ Computation in match works\n")

    // Test 16: Enum with String data - construction and match
    println("[Test 16] Enum with String data")
    var msg Message = Message::Text("Hello, World!")

    // Use match to extract and print the string
    var extracted_text String = match msg {
        Message::Text(s) -> s,
        Message::Error(s) -> s,
        Message::Warning(s) -> s
    }
    println("  Extracted text:", extracted_text)
    assert(extracted_text == "Hello, World!", "Should extract 'Hello, World!'")

    // Test with Error variant
    msg = Message::Error("Something went wrong")
    var error_msg String = match msg {
        Message::Text(s) -> "Text: " + s,
        Message::Error(s) -> "Error: " + s,
        Message::Warning(s) -> "Warning: " + s
    }
    println("  Matched error:", error_msg)
    assert(error_msg == "Error: Something went wrong", "Should format error message")

    // Test with Warning variant
    msg = Message::Warning("Be careful!")
    var warning_msg String = match msg {
        Message::Text(s) -> s,
        Message::Error(s) -> s,
        Message::Warning(s) -> s
    }
    println("  Matched warning:", warning_msg)
    assert(warning_msg == "Be careful!", "Should extract 'Be careful!'")
    println("  ✓ String enum with match works\n")

    println("╔════════════════════════════════════════════════╗")
    println("║         All 16 tests passed!                   ║")
    println("╚════════════════════════════════════════════════╝")
    println()
    println("Tested features:")
    println("  ✓ Simple enums (unit variants)")
    println("  ✓ Enum comparison and assignment")
    println("  ✓ Enum as function parameter/return")
    println("  ✓ Enums with single-parameter data")
    println("  ✓ Enums with multi-parameter data")
    println("  ✓ Different data types in variants")
    println("  ✓ Mixed variants (with/without data)")
    println("  ✓ Match expressions with enum pattern matching")
    println("  ✓ Variable binding in match patterns")
    println("  ✓ Enums with string data and string operations")
}

// Helper functions
func get_status_code(s Status) int {
    if s == Status::Pending {
        return 100
    }
    if s == Status::Running {
        return 200
    }
    if s == Status::Completed {
        return 300
    }
    if s == Status::Failed {
        return 400
    }
    return 0
}

func get_initial_status() Status {
    return Status::Pending
}

func get_running_status() Status {
    return Status::Running
}

func get_final_status() Status {
    return Status::Completed
}

// ============= Enum with Data Helper Functions =============

func process_result(r Result) int {
    // Placeholder - pattern matching will be implemented in future
    return 0
}

func process_value(v Value) int {
    // Placeholder - pattern matching will be implemented in future
    return 0
}

func create_success() Result {
    return Result::Ok(200)
}

func create_error() Result {
    return Result::Error(404)
}

func create_result_from_value(value int) Result {
    return Result::Ok(value)
}
